package cn.iocoder.yudao.module.trade.service.orderpostconfig;

import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
import cn.iocoder.yudao.module.infra.api.config.dto.ConfigDTO;
import cn.iocoder.yudao.module.trade.enums.orderpostback.OrderPostBackConfigTypesEnum;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import cn.iocoder.yudao.module.trade.controller.admin.orderpostconfig.vo.*;
import cn.iocoder.yudao.module.trade.dal.dataobject.orderpostconfig.OrderPostConfigDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.trade.dal.mysql.orderpostconfig.OrderPostConfigMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;

/**
 * 订单回传扣量配置 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class OrderPostConfigServiceImpl implements OrderPostConfigService {

    @Resource
    private OrderPostConfigMapper orderPostConfigMapper;
    @Resource
    private ConfigApi configApi;
    //推广地址
    private static final String DRAINAGE_URL = "post.drainage.type.url.%d";

    @Override
    @CacheEvict(cacheNames = {"order:post:config", "order:post:drainage:config"})
    public Integer createOrderPostConfig(OrderPostConfigSaveReqVO createReqVO) {
        OrderPostConfigDO orderPostConfig = BeanUtils.toBean(createReqVO, OrderPostConfigDO.class);;
        String drainageCode = null;
        do {
            drainageCode = RandomUtil.randomString(6);
        } while (existDrainageCode(drainageCode));
        ConfigDTO config = configApi.getConfigByKey(String.format(DRAINAGE_URL, createReqVO.getDrainageType()));
        if (config == null || StringUtils.isEmpty(config.getValue())) {
            throw new ValidateException("第三方推广地址为空");
        }

        orderPostConfig.setDrainageCode(drainageCode);
        orderPostConfig.setDrainageUrl(config.getValue() + drainageCode);
        wrapperRemark(orderPostConfig);
        return orderPostConfigMapper.insert(orderPostConfig);
    }

    @Override
    @CacheEvict(cacheNames = {"order:post:config", "order:post:drainage:config"})
    public void updateOrderPostConfig(OrderPostConfigSaveReqVO updateReqVO) {
        // 校验存在
        validateOrderPostConfigExists(updateReqVO.getId());
        // 更新
        OrderPostConfigDO updateObj = BeanUtils.toBean(updateReqVO, OrderPostConfigDO.class);
        wrapperRemark(updateObj);
        orderPostConfigMapper.updateById(updateObj);
    }

    /**
     * 添加备注
     * @param configDO
     */
    private void wrapperRemark(OrderPostConfigDO configDO) {
        OrderPostBackConfigTypesEnum type = OrderPostBackConfigTypesEnum.getByType(configDO.getConfigType());
        if (type == null) {
            throw new ValidateException("扣量类型为空");
        }
        String remark = null;
        switch (type) {
            case PERCENT: remark = String.format("订单回传量达到%d%%进行扣量", configDO.getConfigValue()); break;
            case LESS_THEN: remark = String.format("订单金额小于%s元进行扣量", BigDecimal.valueOf(configDO.getConfigValue())
                    .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP)); break;
            case MORE_THEN: remark = String.format("订单金额大于%s元进行扣量", BigDecimal.valueOf(configDO.getConfigValue())
                    .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP)); break;
        }
        configDO.setRemark(remark);
    }

    @Override
    @CacheEvict(cacheNames = {"order:post:config", "order:post:drainage:config"})
    public void deleteOrderPostConfig(Long id) {
        // 校验存在
        validateOrderPostConfigExists(id);
        // 删除
        orderPostConfigMapper.deleteById(id);
    }

    private boolean existDrainageCode(String drainageCode) {
        LambdaQueryWrapperX<OrderPostConfigDO> lambdaQueryWrapper = new LambdaQueryWrapperX<>();
        lambdaQueryWrapper.eq(OrderPostConfigDO::getDrainageCode, drainageCode);
        return orderPostConfigMapper.selectCount(lambdaQueryWrapper) > 0;
    }

    private void validateOrderPostConfigExists(Long id) {
        if (orderPostConfigMapper.selectById(id) == null) {
            throw exception(ORDER_POST_CONFIG_NOT_EXISTS);
        }
    }

    @Override
    public OrderPostConfigDO getOrderPostConfig(Long id) {
        return orderPostConfigMapper.selectById(id);
    }

    @Override
    public PageResult<OrderPostConfigDO> getOrderPostConfigPage(OrderPostConfigPageReqVO pageReqVO) {
        return orderPostConfigMapper.selectPage(pageReqVO);
    }

    @Override
    @Cacheable(cacheNames = {"order:post:config", "order:post:drainage:config"})
    public List<OrderPostConfigDO> listAllConfig() {
        LambdaQueryWrapperX<OrderPostConfigDO> queryWrapperX = new LambdaQueryWrapperX<>();
        queryWrapperX.eq(OrderPostConfigDO::getStatus, 1);
        queryWrapperX.orderByAsc(OrderPostConfigDO::getSort);
        return orderPostConfigMapper.selectList(queryWrapperX);
    }

    @Override
    @Cacheable(cacheNames = "order:post:drainage:config", key = "#drainageCode")
    public OrderPostConfigDO queryByDrainageCode(String drainageCode) {
        LambdaQueryWrapperX<OrderPostConfigDO> lambdaQueryWrapper = new LambdaQueryWrapperX<>();
        lambdaQueryWrapper.eq(OrderPostConfigDO::getDrainageCode, drainageCode);
        return orderPostConfigMapper.selectOne(lambdaQueryWrapper);
    }

}